#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "main.h"
#include "book_management.h"


int main( int argc, char **argv ) {
	if (argc != 3){
		printf("Error\nExpected use: ./library filename1 filename2\n The best option is txt file!\n"); 
		exit(0);
	}
	strcpy(bookFile, argv[1]);
	strcpy(userFile, argv[2]);
	if (!strcmp(bookFile, userFile)){
        printf("Error! The two file names can not be same!\n");
        exit(0);
    }
    int option;
    head = (User*)malloc(sizeof(User));
    head->next = NULL;
    bList = (BookList*) malloc(sizeof (BookList));
    bList->list = (Book*) malloc(sizeof (Book));
    bList->length = 0;
    bList->list->next = NULL;
    load_books(book_f);
    loadUser(user_f, head);
    while (1) {
        printf("-----------The library system----------");
        printf("\n");
        printf("Please choose an option:\n");
        printf("1) Register an account\n2) Login\n3) Search for books\n4) Display all books\n5) Quit\n");
        printf("Option:");
        option = choice();
        switch (option) {
            case 1:
                create_account(head);
                break;
            case 2:
                login(head);
                break;
            case 3:
                findBooks();
                break;
            case 4:
                displayBooks(bList);
                break;
            case 5:
                storeUser(user_f);
                store_books(book_f);
                printf("\nThanks for using the library!\n");
                return 0;
            default:
                printf("Sorry, the option you entered was invalid, please try again.\n");
        }
    }
}

void findBooks() {
    int option;
    while (1){
        printf("Please choose an option:\n1) Find books by title\n2) Find books by author\n3) Find books by year\n4) Quit\n");
        printf("Option:");
        option = choice();
        switch (option) {
            case 1:
                printf("Please enter the title:");
                char type[20];
                scanf("%s", type);
                find_book_by_title(type);
                break;
            case 2:
                printf("Please enter the author:");
                char author[20];
                scanf("%s", author);
                find_book_by_author(author);
                break;
            case 3:
                printf("Please enter the year:");
                int year;
                scanf("%i", &year);
                find_book_by_year(year);
                break;
            case 4:
                return;
            default:
                printf("Sorry, the option you entered was invalid, please try again.\n");
        }
    }
}

BookList find_book_by_title (const char *title){
    BookList bTitle = *bList;

    int cnt = 0;
    printf("+----------------------------------Book Lists-------------------------------------+\n");
    printf("|   %-5s %-25s %-25s %-10s %-5s   |\n","ID","Title","Author","Year","Copies");
    printf("+---------------------------------------------------------------------------------+\n");
    while (bTitle.list->next != NULL){
        if (!strcmp(bTitle.list->next->title, title)) {

            printf("|   %-5i %-25s %-25s %-12i %-i      |\n", bTitle.list->next->id, bTitle.list->next->title,
                   bTitle.list->next->authors, bTitle.list->next->year, bTitle.list->next->copies);
            cnt++;
        }
        bTitle.list = bTitle.list->next;
    }
    printf("+---------------------------------------------------------------------------------+\n");

    if(cnt == 0){
        printf("Sorry, can not find the book!\n\n");
    }
    return bTitle;
}

BookList find_book_by_author (const char *author){
    BookList bAuthor = *bList;

    int cnt = 0;
    printf("+----------------------------------Book Lists-------------------------------------+\n");
    printf("|   %-5s %-25s %-25s %-10s %-5s   |\n","ID","Title","Author","Year","Copies");
    printf("+---------------------------------------------------------------------------------+\n");
    while (bAuthor.list->next != NULL){
        if (!strcmp(bAuthor.list->next->authors, author)) {

            printf("|   %-5i %-25s %-25s %-12i %-i      |\n", bAuthor.list->next->id, bAuthor.list->next->title,
                   bAuthor.list->next->authors, bAuthor.list->next->year, bAuthor.list->next->copies);
            cnt++;
        }
        bAuthor.list = bAuthor.list->next;
    }
    printf("+---------------------------------------------------------------------------------+\n");

    if(cnt == 0){
        printf("Sorry, can not find the book!\n\n");
    }
    return bAuthor;
}

BookList find_book_by_year (unsigned int year){
    BookList bYear = *bList;
    int cnt = 0;
    printf("+----------------------------------Book Lists-------------------------------------+\n");
    printf("|   %-5s %-25s %-25s %-10s %-5s   |\n","ID","Title","Author","Year","Copies");
    printf("+---------------------------------------------------------------------------------+\n");
    while (bYear.list != NULL){
        if (bYear.list->year == year) {

            printf("|   %-5i %-25s %-25s %-12i %-i      |\n", bYear.list->id, bYear.list->title,
                   bYear.list->authors, bYear.list->year, bYear.list->copies);
            cnt++;

        }
        bYear.list = bYear.list->next;
    }
    printf("+---------------------------------------------------------------------------------+\n");

    if(cnt == 0){
        printf("Sorry, can not find the book!\n\n");
    }
    return bYear;
}

void displayBooks(BookList *pList) {
    Book *p = pList->list;
    printf("+----------------------------------Book Lists-------------------------------------+\n");
    printf("|   %-5s %-25s %-25s %-10s %-5s   |\n","ID","Title","Author","Year","Copies");
    printf("+---------------------------------------------------------------------------------+\n");
    while (p->next != NULL){
        printf("|   %-5i %-25s %-25s %-12i %-i      |\n", p->next->id, p->next->title, p->next->authors,
               p->next->year, p->next->copies);
        p = p->next;
    }
    printf("+---------------------------------------------------------------------------------+\n");
}

void login(User *user) {
    User *rear = user;
    printf("-----------User login----------\n");
    char name[50];
    char password[50];
    printf("Please enter your username:");
    scanf("%s",name);
    printf("Please enter your password:");
    scanf("%s",password);
    while(rear != NULL) {
        if(!strcmp(rear->name, name) && !strcmp(rear->password, password)){
            printf("Login succeed!\n");
            int option;
            printf("(Load in as %s)\n",name);
            while (1) {
                printf("Please choose an option:\n");
                printf("1) Borrow a book\n2) Return a book\n3) Search for books\n4) Display all books\n5) Quit\n");
                printf("Option:");
                option = choice();
                switch (option) {
                    case 1:
                        borrow_book(head, bList->list, name);
                        break;
                    case 2:
                        return_book(head, bList->list, name);
                        break;
                    case 3:
                        findBooks();
                        break;
                    case 4:
                        displayBooks(bList);
                        break;
                    case 5:
                        printf("\nLogging out...\n");
                        return;
                    default:
                        printf("Sorry, the option you entered was invalid, please try again.\n");
                }
            }
        }
        rear = rear->next;
    }
    if(!strcmp(name,"librarian") && !strcmp(password, "librarian")){
        int option;
        printf("(Load in as %s)\n",name);
        while (1) {
            printf("Please choose an option:\n");
            printf("1) Add a book\n2) Remove a book\n3) Search for books\n4) Display all books\n5) Quit\n");
            printf("Option:");
            Book *books = (Book*) malloc(sizeof (Book));
            option = choice();
            switch (option) {
                case 1:
                    add_book(*books);
                    break;
                case 2:
                    remove_book(*books);
                    break;
                case 3:
                    findBooks();
                    break;
                case 4:
                    displayBooks(bList);
                    break;
                case 5:
                    printf("\nLogging out...\n");
                    return;
                default:
                    printf("Sorry, the option you entered was invalid, please try again.\n");
            }
        }
    }
    printf("The username or the password you entered is wrong!\n");
}

int return_book(User *pUser, Book *pBook, char *name) {
    User *Urear = pUser;
    Book *Brear = pBook;
    while (Urear != NULL){
        if(!strcmp(name, Urear->name)){
            break;
        }
        Urear = Urear->next;
    }
    if(Urear->loan == 0){
        printf("Error! You didn't borrow any book!\n");
        return -1;
    }
    int choice;
    while (Brear->next != NULL){
        if(Urear->loan == Brear->next->id){

            printf("%-5s %-25s %-25s %-10s\n","ID","Title","Author","Year");
            printf("%-5i %-25s %-25s %-12i %d\n", Brear->next->id, Brear->next->title, Brear->next->authors,
                   Brear->next->year ,Brear->next->copies);
            printf("You has borrowed this book, please enter the book ID:");
            scanf("%i",&choice);
            if(choice == Brear->next->id){
                Brear->next->copies++;
                Urear->loan = 0;
            } else{
                printf("Error! You entered a wrong number!\n");
                return -1;
            }
            break;
        }
        Brear = Brear->next;
    }
    return 0;

}

int borrow_book(User *pUser, Book *pBook, char* name) {
    User *Urear = pUser;
    Book *Brear = pBook;
    while (Urear != NULL){
        if(!strcmp(name, Urear->name)){
            break;
        }
        Urear = Urear->next;
    }

    if(Urear->loan != 0){
        printf("Error! You must return a book before you borrow a new one!\n");
        return -1;
    }
    int bookId = 0;
    displayBooks(bList);
    printf("Please enter which book you want to borrow? Please enter the book ID:");
    scanf("%i", &bookId);
    while (Brear->next != NULL){
        if(Brear->next->id == bookId){
            if(Brear->next->copies > 0){
                Brear->next->copies--;
                Urear->loan = Brear->next->id;
                printf("Borrow succeed!\n");
                break;
            } else{
                printf("Error! The book you wanted to borrow is unavailable!\n");
                return -1;
            }
        }
        Brear = Brear->next;
    }
    return 0;
}

int add_book(Book book){
    char title[50];
    char author[50];
    int year;
    int copies;
    Book *rear = bList->list;
    Book *abooks;
    printf("Please enter the book title:");
    scanf("%s",title);
    printf("Please enter the book author:");
    scanf("%s",author);
    printf("Please enter the year of the book:");
    scanf("%i",&year);
    printf("Please enter the copies of the book:");
    scanf("%i",&copies);
    if(year < 0 || year > 2022){
        printf("Error! The year you entered was illegal.\n");
        return -1;
    }
    abooks = (Book*) malloc(sizeof (Book));
    abooks->title = (char *) malloc(sizeof (title) + 1);
    abooks->authors = (char *) malloc(sizeof (author) + 1);
    strcpy(abooks->title, title);
    strcpy(abooks->authors, author);
    abooks->year = year;
    abooks->copies = copies;
    abooks->next = NULL;
    while(rear->next != NULL) {
        rear = rear->next;
    }
    bList->length++;
    abooks->id = bList->length;
    rear->next = abooks;
    printf("Add book succeed!\n");
    return 0;
}

int remove_book(Book book){
    int id;
    int isRemove = 0;
    displayBooks(bList);
    printf("Which book you want to remove? Please enter the ID:");
    scanf("%i",&id);
    Book *p = bList->list;
    User *Urear = head;
    int isExist = 0;
    while (Urear != NULL){
        if(Urear->loan == id){
            isExist = 1;
            break;
        }
        Urear = Urear->next;
    }
    if (isExist == 1){
        printf("Sorry, this book has not been returned by some users, it can not be removed temporarily!\n");
    }
    while (p->next != NULL){
        if (p->next->next != NULL) {
            if (p->next->id == id) {
                free(p->next);
                p->next = p->next->next;
                isRemove = 1;
                break;
            }
        } else if(p->next->id == id){
            free(p->next);
            p->next = NULL;
            isRemove = 1;
            break;
        }
        p = p->next;
    }
    if(isRemove == 0){
        printf("Error! Can't find the book ID!\n");
    } else{
        printf("Remove succeed!\n");
    }
    return 0;
}

int loadUser(FILE *fp, User *user){
    fp = fopen(userFile,"r");
    if (fp == NULL)
    {
        fp = fopen(userFile, "w");
    }
    User *rear = user;
    User *user_data;

    while (1){
        char name[50];
        int id;
        char password[50];
        int loan;
        if(fscanf(fp,"%s %d %s %d\n", name, &id, password, &loan) == EOF){
            break;
        } else{
            user_data= (User*) malloc(sizeof (User));
            strcpy(user_data->name,name);
            strcpy(user_data->password,password);
            user_data->id = id;
            user_data->loan = loan;
            user_data->next = NULL;
        }
        while(rear->next != NULL) {
            rear = rear->next;
        }
        rear->next = user_data;
    }
    fclose(fp);
    return 0;
}

int load_books(FILE *file){
    file = fopen(bookFile,"r");
    if (file == NULL)
    {
        file = fopen(bookFile, "w");
    }
    Book *rear = bList->list;
    Book *book_data;
    while (1){
        int id;
        char title[50];
        char authors[50];
        int year;
        int copies;
        if(fscanf(file,"%d\t%s\t%s\t%d\t%d\n", &id, title, authors, &year, &copies) == EOF){
            break;
        } else{
            book_data= (Book*) malloc(sizeof (Book));
            book_data->title = (char *) malloc(sizeof (char ) * 50);
            book_data->authors = (char *) malloc(sizeof (char ) * 50);
            strcpy(book_data->title,title);
            strcpy(book_data->authors,authors);
            book_data->id = id;
            book_data->year = year;
            book_data->copies = copies;
            book_data->next = NULL;
        }
        while(rear->next != NULL) {
            rear = rear->next;
        }
        rear->next = book_data;
        bList->length++;
    }
    fclose(file);
    return 0;
}

void storeUser(FILE *fp) {
    fp = fopen(userFile, "w");
    User *p = head->next;
    while (p!=NULL){
        fprintf(fp, "%s %i %s %d\n", p->name, p->id, p->password, p->loan);
        free(p);
        p = p->next;
    }
    fclose(fp);
}

int store_books(FILE *file){
    file = fopen(bookFile, "w");
    Book *p = bList->list->next;
    while (p!=NULL){
        fprintf(file, "%i\t%s\t%s\t%i\t%i\n",p->id,p->title,p->authors,p->year,p->copies);
        free(p);
        p = p->next;
    }
    fclose(file);
    return 0;
}

void create_account(User *user) {
    User *rear = user;
    printf("-----------Register----------\n");
    User *new_user = (User*) malloc(sizeof (User));
    new_user -> next = NULL;
    char name[50];
    int id;
    char password[50];
    printf("Please enter your username:");
    scanf("%s",name);
    if(!strcmp(name,"librarian")){
        printf("Sorry! The account has already been registered!\n");
        return;
    }
    printf("Please enter your student ID:");
    scanf("%d",&id);
    printf("Please enter your password:");
    scanf("%s",password);
    while(rear->next != NULL) {
        if(rear->next->id == id){
            printf("Sorry! The account has already been registered!\n");
            return;
        }
        rear = rear->next;
    }
    strcpy(new_user->name, name);
    new_user->id = id;
    new_user->loan = 0;
    strcpy(new_user->password, password);
    printf("Register succeed!\n");
    rear->next = new_user;
}

int choice() {
    int option;
    char input[100];
    scanf("%10s",input);
    option = (int)atoi(input);
    return option;
}
